package my.mall.admin.api.service

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper
import com.baomidou.mybatisplus.core.metadata.IPage
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import my.mall.admin.api.pojo.login.LoginInfo
import my.mall.admin.api.pojo.media.MediaItem
import my.mall.admin.api.pojo.media.MediaListParam
import my.mall.admin.api.pojo.media.MediaSaveParam
import my.mall.common.exception.WebBaseException
import my.mall.common.pojo.CommonResp
import my.mall.common.pojo.DeleteParam
import my.mall.common.pojo.PageParam
import my.mall.common.pojo.PageResp
import my.mall.common.util.RespUtils
import my.mall.db.entity.Media
import my.mall.db.entity.MediaGroup
import my.mall.db.mapper.MediaGroupMapper
import my.mall.db.mapper.MediaMapper
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.util.StringUtils
import java.util.stream.Collectors

@Service
open class MediaService(
    private val mediaMapper: MediaMapper,
    private val mediaGroupMapper: MediaGroupMapper
) : ServiceImpl<MediaMapper, Media>() {

    open fun getMediaList(loginInfo: LoginInfo, param: MediaListParam, page: PageParam): CommonResp<PageResp<Media>> {
        var iPage: IPage<Media> = Page(page.pageNum, page.pageSize)
        iPage = mediaMapper.selectPage(
            iPage, QueryWrapper<Media>()
                .select(Media.ID, Media.GROUP_ID, Media.MEDIA_NAME, Media.MEDIA_URL)
                .eq(Media.STORE_ID, loginInfo.storeId).eq(Media.DELETED_FLAG, 0)
                .eq(param.groupId != null, Media.GROUP_ID, param.groupId)
                .like(StringUtils.hasLength(param.mediaName), Media.MEDIA_NAME, param.mediaName)
                .orderByDesc(Media.ID)
        )
        for (media in iPage.records) {
            media.mediaUrl = media.mediaUrl
        }
        return RespUtils.success(iPage.current, iPage.size, iPage.total, iPage.records)
    }

    @Transactional(rollbackFor = [Exception::class])
    open fun saveMedia(loginInfo: LoginInfo, param: MediaSaveParam) {
        if (noMediaGroup(param.groupId)) {
            throw WebBaseException(400, "素材组不存在!")
        }
        val itemList: List<MediaItem>? = param.mediaList
        val mediaList: MutableList<Media> = ArrayList(
            itemList!!.size
        )
        for (item in itemList) {
            val media = Media()
            media.mediaName = item.mediaName
            media.mediaUrl = item.mediaUrl
            media.groupId = param.groupId
            media.storeId = loginInfo.storeId
            mediaList.add(media)
        }
        if (saveBatch(mediaList)) {
            mediaGroupMapper.addMediaNum(loginInfo.storeId, param.groupId, mediaList.size)
        }
    }

    @Transactional(rollbackFor = [Exception::class])
    open fun deleteMedia(loginInfo: LoginInfo, ids: List<Long?>?) {
        val mediaMap = mediaMapper.selectList(
            QueryWrapper<Media>()
                .select(Media.ID, Media.GROUP_ID)
                .eq(Media.STORE_ID, loginInfo.storeId).`in`(Media.ID, ids)
        ).stream().collect(Collectors.groupingBy(Media::groupId))
        for ((key, value) in mediaMap) {
            if (mediaMapper.delete(
                    UpdateWrapper<Media>()
                        .set(Media.DELETED_FLAG, 1)
                        .eq(Media.STORE_ID, loginInfo.storeId)
                        .eq(Media.GROUP_ID, key)
                        .`in`(Media.ID, value.stream().map(Media::id).collect(Collectors.toList()))
                ) > 0
            ) {
                mediaGroupMapper.subMediaNum(loginInfo.storeId, key, value.size)
            }
        }
    }

    @Transactional(rollbackFor = [Exception::class])
    open fun updateById(loginInfo: LoginInfo, media: Media) {
        val oldMedia = mediaMapper.selectOne(
            QueryWrapper<Media>()
                .select(Media.GROUP_ID)
                .eq(Media.ID, media.id).eq(Media.STORE_ID, loginInfo.storeId)
        ) ?: return
        if (media.groupId != null) {
            if (media.groupId == oldMedia.groupId) {
                return
            }
            if (noMediaGroup(media.groupId)) {
                throw WebBaseException(400, "素材组不存在!")
            }
        }
        if (mediaMapper.updateById(media) > 0 && media.groupId != null) {
            mediaGroupMapper.subMediaNum(loginInfo.storeId, oldMedia.groupId, 1)
            mediaGroupMapper.addMediaNum(loginInfo.storeId, media.groupId, 1)
        }
    }

    private fun noMediaGroup(groupId: Long?): Boolean {
        return mediaGroupMapper.selectOne(
            QueryWrapper<MediaGroup>()
                .select(MediaGroup.ID).eq(MediaGroup.ID, groupId)
        ) == null
    }

    open fun getMediaGroupList(storeId: Long?): List<MediaGroup> {
        return mediaGroupMapper.selectList(
            QueryWrapper<MediaGroup>()
                .select(MediaGroup.ID, MediaGroup.GROUP_NAME, MediaGroup.MEDIA_NUM)
                .eq(MediaGroup.STORE_ID, storeId).eq(MediaGroup.DELETED_FLAG, 0)
        )
    }

    open fun saveOrEditGroup(loginInfo: LoginInfo, mediaGroup: MediaGroup) {
        mediaGroup.storeId = loginInfo.storeId
        if (mediaGroup.id != null) {
            mediaGroupMapper.updateById(mediaGroup)
        } else {
            mediaGroupMapper.insert(mediaGroup)
        }
    }

    open fun deleteMediaGroup(loginInfo: LoginInfo, param: DeleteParam) {
        mediaGroupMapper.delete(
            UpdateWrapper<MediaGroup>()
                .eq(MediaGroup.ID, param.id).eq(MediaGroup.STORE_ID, loginInfo.storeId)
        )
    }
}
